/**********************************************
Main Source of our App - Root of Program
**********************************************/

// LEAN AND MEAN is the leanest of the mean!!
//	*Necessary for networking*
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <iostream>

#include <tchar.h>

#if _DEBUG
// For Leak detection
// *Make sure we aren't leaking any memory*
#include <vld.h>
#endif

#include <ctime>

// Runs our application
#include "App.h"

// Handles keyboard input via windows messages
#include "input\WinM_InputHandler.h"
CWinM_InputHandler *g_Input_Handler = CWinM_InputHandler::GetInstance();

LRESULT CALLBACK WindowProc( HWND _hWnd, unsigned int _nMsg, WPARAM _wParam, LPARAM _lParam )
{
	switch( _nMsg )
	{
		//	To skip ALT pop up menu (system menu)
		case WM_SYSKEYUP:
		case WM_SYSCHAR:
			return(0);

		case WM_KEYDOWN:
		{
			g_Input_Handler->Acion_PressKey( _wParam );
			break;
		}

		case WM_KEYUP:
		{
			g_Input_Handler->Acion_UnPressKey( _wParam );
			break;
		}


		case WM_CLOSE:
		{
			DestroyWindow( _hWnd );
			break;
		}
		//	lose/gain focus
		case WM_ACTIVATE:
		{
			if (LOWORD(_wParam) == WA_INACTIVE)
			{
				// TODO pause game code here
			}
			else
			{
			}
			break;
		}
		case WM_DESTROY: 	
		{
			PostQuitMessage(0);
			return(0);
		}

		default:
		break;
	}
	return ( DefWindowProc( _hWnd, _nMsg, _wParam, _lParam) );
};

// Register the Window
BOOL RegisterWindowClass(HINSTANCE hInstance)
{
	WNDCLASSEX	winClassEx;
	winClassEx.cbSize			= sizeof(winClassEx);
	winClassEx.style			= CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
	winClassEx.lpfnWndProc		= WindowProc;
	winClassEx.cbClsExtra		= 0;
	winClassEx.cbWndExtra		= 0;
	winClassEx.hInstance		= hInstance;
	winClassEx.hIcon			= LoadIcon(hInstance, NULL);
	winClassEx.hIconSm			= LoadIcon(hInstance, NULL);
	winClassEx.hCursor			= LoadCursor(NULL, IDC_ARROW);
	winClassEx.hbrBackground	= (HBRUSH)GetStockObject(BLACK_BRUSH);
	winClassEx.lpszMenuName		= NULL; 
	winClassEx.lpszClassName	= "Project_Coop";
	return RegisterClassEx(&winClassEx);
}

// Generate our actual window
HWND MakeWindow(HINSTANCE hInstance, LONG lWindowWidth, LONG lWindowHeight, bool bIsWindowed)
{
	// Setup window style flags
	// TODO: Add notes for the different types 
	DWORD dwWindowStyleFlags = WS_POPUP | WS_CAPTION | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU | WS_VISIBLE;

	RECT rWindow;
	rWindow.left	= 0;
	rWindow.top		= 0;
	rWindow.right	= lWindowWidth;
	rWindow.bottom	= lWindowHeight;

	// Get the dimensions of a window that will have a client rect that
	// will really be the resolution we're looking for.
	AdjustWindowRectEx(&rWindow, dwWindowStyleFlags, FALSE,	WS_EX_APPWINDOW);
	
	// Calculate the width/height of that window's dimensions
	int nWindowWidth	= rWindow.right - rWindow.left;
	int nWindowHeight	= rWindow.bottom - rWindow.top;

	//	Create the window
	return CreateWindowEx(WS_EX_APPWINDOW,											//	Extended Style flags.
							"Project_Coop",											//	Window Class Name.
							"Project Coop",											//	Title of the Window.
							dwWindowStyleFlags,										//	Window Style Flags.
							(GetSystemMetrics(SM_CXSCREEN)/2) - (nWindowWidth/2),	//	Window Start Point (x, y). 
							(GetSystemMetrics(SM_CYSCREEN)/2) - (nWindowHeight/2),	//		-Does the math to center the window over the desktop.
							nWindowWidth,											//	Width of Window.
							nWindowHeight,											//	Height of Window.
							NULL,													//	Handle to parent window.
							NULL,													//	Handle to menu.
							hInstance,												//	Application Instance.
							NULL);													//	Creation parameters.
};

// The Entry Point function
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
	HWND hWnd = nullptr;
	CApp app;
	MSG msg;
	//rand() 
	srand( unsigned( time( 0 ) ) );

	//	Register the window class
	if (!RegisterWindowClass(hInstance))
	{
		OutputDebugStringA( "Unable to register window class" );
		return 0;
	}

	hWnd = MakeWindow(hInstance, 640, 360, true);
	if (!hWnd)
	{
		OutputDebugStringA( "Unable to make window" );
		return 0;
	}

	ShowWindow(hWnd, nCmdShow);
	UpdateWindow(hWnd);

	// Initialize the input handler
	g_Input_Handler->Init();

	// Initialize the application
	app.Init( hWnd, 640, 360 );


	//	Enter main event loop
	while( true )
	{
		while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{ 
			//	Translate any accelerator keys
			TranslateMessage(&msg);

			//	Send the message to the window proc
			DispatchMessage(&msg);
		}
		
		// If we closed the window
		if (msg.message == WM_QUIT)
			break;

		// Update the application
		if( app.main() == false )
			break;

		// TODO: Console update goes here.

		Sleep(1);
	}

	// Clean up the dynamic memory
	app.Release();

	// Release the input handler
	g_Input_Handler->Release();

	UnregisterClass("Project_Coop", hInstance);

	return 0;
}
